/*! https://mths.be/base64 v<%= version %> by @mathias | MIT license */
;(function(root) {
  
    // Detect free variables `exports`.
    var freeExports = typeof exports == 'object' && exports;
  
    // Detect free variable `module`.
    var freeModule = typeof module == 'object' && module &&
      module.exports == freeExports && module;
  
    // Detect free variable `global`, from Node.js or Browserified code, and use
    // it as `root`.
    var freeGlobal = typeof global == 'object' && global;
    if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
      root = freeGlobal;
    }
  
    /*--------------------------------------------------------------------------*/
  
    var InvalidCharacterError = function(message) {
      this.message = message;
    };
    InvalidCharacterError.prototype = new Error;
    InvalidCharacterError.prototype.name = 'InvalidCharacterError';
  
    var error = function(message) {
      // Note: the error messages used throughout this file match those used by
      // the native `atob`/`btoa` implementation in Chromium.
      throw new InvalidCharacterError(message);
    };
  
    var TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    // http://whatwg.org/html/common-microsyntaxes.html#space-character
    var REGEX_SPACE_CHARACTERS = /<%= spaceCharacters %>/g;
  
    // `decode` is designed to be fully compatible with `atob` as described in the
    // HTML Standard. http://whatwg.org/html/webappapis.html#dom-windowbase64-atob
    // The optimized base64-decoding algorithm used is based on @atk’s excellent
    // implementation. https://gist.github.com/atk/1020396
    var decode = function(input) {
      input = String(input)
        .replace(REGEX_SPACE_CHARACTERS, '');
      var length = input.length;
      if (length % 4 == 0) {
        input = input.replace(/==?$/, '');
        length = input.length;
      }
      if (
        length % 4 == 1 ||
        // http://whatwg.org/C#alphanumeric-ascii-characters
        /[^+a-zA-Z0-9/]/.test(input)
      ) {
        error(
          'Invalid character: the string to be decoded is not correctly encoded.'
        );
      }
      var bitCounter = 0;
      var bitStorage;
      var buffer;
      var output = '';
      var position = -1;
      while (++position < length) {
        buffer = TABLE.indexOf(input.charAt(position));
        bitStorage = bitCounter % 4 ? bitStorage * 64 + buffer : buffer;
        // Unless this is the first of a group of 4 characters…
        if (bitCounter++ % 4) {
          // …convert the first 8 bits to a single ASCII character.
          output += String.fromCharCode(
            0xFF & bitStorage >> (-2 * bitCounter & 6)
          );
        }
      }
      return output;
    };
  
    // `encode` is designed to be fully compatible with `btoa` as described in the
    // HTML Standard: http://whatwg.org/html/webappapis.html#dom-windowbase64-btoa
    var encode = function(input) {
      input = String(input);
      if (/[^\0-\xFF]/.test(input)) {
        // Note: no need to special-case astral symbols here, as surrogates are
        // matched, and the input is supposed to only contain ASCII anyway.
        error(
          'The string to be encoded contains characters outside of the ' +
          'Latin1 range.'
        );
      }
      var padding = input.length % 3;
      var output = '';
      var position = -1;
      var a;
      var b;
      var c;
      var d;
      var buffer;
      // Make sure any padding is handled outside of the loop.
      var length = input.length - padding;
  
      while (++position < length) {
        // Read three bytes, i.e. 24 bits.
        a = input.charCodeAt(position) << 16;
        b = input.charCodeAt(++position) << 8;
        c = input.charCodeAt(++position);
        buffer = a + b + c;
        // Turn the 24 bits into four chunks of 6 bits each, and append the
        // matching character for each of them to the output.
        output += (
          TABLE.charAt(buffer >> 18 & 0x3F) +
          TABLE.charAt(buffer >> 12 & 0x3F) +
          TABLE.charAt(buffer >> 6 & 0x3F) +
          TABLE.charAt(buffer & 0x3F)
        );
      }
  
      if (padding == 2) {
        a = input.charCodeAt(position) << 8;
        b = input.charCodeAt(++position);
        buffer = a + b;
        output += (
          TABLE.charAt(buffer >> 10) +
          TABLE.charAt((buffer >> 4) & 0x3F) +
          TABLE.charAt((buffer << 2) & 0x3F) +
          '='
        );
      } else if (padding == 1) {
        buffer = input.charCodeAt(position);
        output += (
          TABLE.charAt(buffer >> 2) +
          TABLE.charAt((buffer << 4) & 0x3F) +
          '=='
        );
      }
  
      return output;
    };
  
    var base64 = {
      'encode': encode,
      'decode': decode,
      'version': '<%= version %>'
    };
  
    // Some AMD build optimizers, like r.js, check for specific condition patterns
    // like the following:
    if (
      typeof define == 'function' &&
      typeof define.amd == 'object' &&
      define.amd
    ) {
      define(function() {
        return base64;
      });
    }	else if (freeExports && !freeExports.nodeType) {
      if (freeModule) { // in Node.js or RingoJS v0.8.0+
        freeModule.exports = base64;
      } else { // in Narwhal or RingoJS v0.7.0-
        for (var key in base64) {
          base64.hasOwnProperty(key) && (freeExports[key] = base64[key]);
        }
      }
    } else { // in Rhino or a web browser
      root.base64 = base64;
    }
  
  }(this));